package com.bds.btcdc.adapter.huobi.trade.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bds.btcdc.adapter.huobi.trade.HuobiClient;
import com.bds.btcdc.adapter.huobi.trade.model.HuobiOrder;
import com.bds.btcdc.adapter.service.ITradeService;
import com.bds.btcdc.api.model.*;
import com.bds.btcdc.model.UserKeys;
import com.bds.btcdc.service.UserKeysService;
import com.bds.btcdc.util.Const;
import com.bds.btcdc.util.EhcacheUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author: kevin
 * @date: 2018/5/9
 * @description:
 */
@Service
public class HuobiTradeService implements ITradeService {
    private final Logger logger = LoggerFactory.getLogger(getClass());
    private DecimalFormat df = new DecimalFormat(Const.END_WITH_COUNT);
    @Autowired
    private UserKeysService userKeysService;


    @Override
    public Result makeOrder(Order order) {
        long user_id=order.getUserId();
        UserKeys keys = userKeysService.getHuobiKeys(user_id);
        String huobi_id=keys.getExtra_id();
        HuobiClient client=HuobiClient.getInstance(user_id,keys.getAccess_key(),keys.getSecret_key(),huobi_id);

        HuobiOrder huobiOrder=new HuobiOrder();
        huobiOrder.setAccount_id(huobi_id);
        String type=order.getType();
        //buy-limit,sell-limit
        if("buy".equals(type)){
            huobiOrder.setType("buy-limit");
        }else if("sell".equals(type)){
            huobiOrder.setType("sell-limit");
        }
        huobiOrder.setPrice(String.valueOf(order.getPrice()));
        huobiOrder.setAmount(String.valueOf(order.getNum()));
        huobiOrder.setSource("api");
        huobiOrder.setSymbol(order.getSymbol().replace("_",""));
        String json = client.makeOrder(huobiOrder);

        Result rst=new Result();
        if(json==null){
            rst.setResult(Const.FAIL,"下单失败，下单记录已保存");
            logger.error("HUOBI下单api发送失败");
            return rst;
        }else{
            OrderResponse response=new OrderResponse();
            JSONObject obj=JSONObject.parseObject(json);
            String status=obj.getString("status");
            if(!"ok".equals(status)){
                response.setStatus(status);
                rst.setData(response);
                rst.setCode(Const.FAIL);
                logger.error("HUOBI下单api返回status状态失败"+json);
                return rst;
            }else{
                String data=obj.getString("data");
                response.setStatus(status);
                response.setOrder_id(data);
                rst.setCode(Const.SUC);
                rst.setData(response);
                logger.info("HUOBI下单成功");
                return rst;
            }
        }
    }

    @Override
    public Result cancelOrder(long userId, String orderId) {
        return null;
    }

    @Override
    public Result getOrder(long userId, String orderId) {
        Result rst=new Result();
        UserKeys keys = userKeysService.getHuobiKeys(userId);
        String huobi_id=keys.getExtra_id();
        HuobiClient client=HuobiClient.getInstance(userId,keys.getAccess_key().trim(),keys.getSecret_key().trim(),huobi_id);
        String json = client.getOrder(orderId);
        if(json==null){
            rst.setResult(Const.FAIL,"HUOBI API服务异常");
            return rst;
        }else {
            JSONObject obj=JSONObject.parseObject(json);
            String status=obj.getString("status");
            if (!"ok".equals(status)){
                rst.setResult(Const.FAIL,"HUOBI API返回失败状态");
                return rst;
            }else {
                JSONObject data=obj.getJSONObject("data");
                String price=data.getString("price");//单价
                String finish_time=data.getString("finished-at");//最后成交时间
                String amount=data.getString("field-amount");//已成交数量
                OrderInfo info=new OrderInfo();
                info.setApi_id(orderId);
                info.setExchange(Const.HUOBI.EXCHANGE);
                info.setAmount(amount);
                info.setPrice(price);
                info.setFinish_time(finish_time);
                rst.setResult(Const.SUC,info);
                return rst;
            }
        }
    }

    @Override
    public Result getAccount(UserKeys keys) {
        logger.info("获取huobi资产。。");
        Result rst=new Result();
        try {
            AccountInfo accountInfo=new AccountInfo();
            HuobiClient client=HuobiClient.getInstance(keys.getUser_id(),keys.getAccess_key().trim(),keys.getSecret_key().trim(),keys.getExtra_id());
            String json = client.getBalance();
//            logger.info("huobi json== "+json);
            JSONObject obj=JSONObject.parseObject(json);
            String status=obj.getString("status");
            //HUOBI api返回的资产信息，币种可用数量和冻结数量不在一起，做整合
            Map<String,Asset> temp=new HashMap<>();
            List<Asset> assets=new ArrayList<>();
            if ("ok".equals(status)){
                JSONObject data=obj.getJSONObject("data");
                JSONArray list=data.getJSONArray("list");
                for (int i = 0; i < list.size(); i++) {
                    JSONObject asset_obj = (JSONObject) list.get(i);
                    String currency = asset_obj.getString("currency");
                    String type = asset_obj.getString("type");
                    String balance = asset_obj.getString("balance");
                    BigDecimal _balance=new BigDecimal(balance);
                    if (_balance.compareTo(BigDecimal.ZERO)==0)
                        continue;
                    Asset asset=temp.get(currency);
                    if (asset==null)
                        asset=new Asset();
                    if ("trade".equals(type)){
                        asset.setCount(df.format(_balance));
                    }else if("frozen".equals(type)){
                        asset.setFreez_count(df.format(_balance));
                    }
                    asset.setCurrency(currency);

                    //只返回不为0 的币种
                    String last_price=null;
                    if(BigDecimal.ZERO.compareTo(asset_obj.getBigDecimal("balance"))!=0) {//过滤掉 为0的币种
                        if (currency.toUpperCase().equals("USDT")){
                            last_price="1.000";
                        }else {
                            //从缓存中取出 usdt币对的最新交易价格
                            String key=Const.HUOBI.EXCHANGE+"#"+currency+"_usdt";
                            last_price = EhcacheUtils.getInstance().getCache(key);
                            if(StringUtils.isEmpty(last_price)){
                                //缓存中没有，去api获取
                                HuobiClient client2=HuobiClient.getInstance();
                                last_price=client2.getPriceBySymbol(currency+"usdt");
                            }
                        }
                        asset.setLast_price(last_price);
                    }
                    //设置可用金额，冻结金额
                    if(asset.getCount()!=null&&last_price!=null){
                        BigDecimal amount=new BigDecimal(last_price).multiply(new BigDecimal(asset.getCount()));
                        asset.setAmount(df.format(amount));
                    }
                    if(asset.getFreez_count()!=null){
                        BigDecimal freez=new BigDecimal(last_price).multiply(new BigDecimal(asset.getFreez_count()));
                        asset.setFreez(df.format(freez));
                    }

                    temp.put(currency,asset);
                }
                for (Asset asset:temp.values()){
                    if (asset.getCount()==null)
                        asset.setCount("0.000");
                    if (asset.getFreez_count()==null)
                        asset.setFreez_count("0.000");
                    assets.add(asset);
                }
                accountInfo.setAssetList(assets);
                accountInfo.setUserId(keys.getUser_id());
                accountInfo.setExchange(Const.HUOBI.EXCHANGE);
                rst.setCode(Const.SUC);
                rst.setData(accountInfo);
            }else {
                rst.setCode(Const.FAIL);
                rst.setMsg("请求失败，参数或服务器异常");
            }
        } catch (Exception e) {
            e.printStackTrace();
            rst.setCode(Const.FAIL);
            rst.setMsg("请求失败，程序异常");
        }
        return rst;
    }
}
